home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / MAGS.ZIP / VLAD#2.ZIP / ARTICLE.2_5 < prev    next >
Encoding:
Text File  |  1994-10-30  |  9.5 KB  |  268 lines

  1.  
  2.            C O D E   O P T I M I Z A T I O N
  3.                 An Assembly Guide
  4.                    Written by
  5.              D   A   R   K   M   A   N   /   V   L   A   D
  6.  
  7.  
  8. -------------------------------------------------
  9. Use the AL/AX register instead of other registers
  10. -------------------------------------------------
  11.   Sometimes it is more optimized to use the AL/AX register instead of the
  12. other registers, comparing with registers could be done like this:
  13.  
  14.          cmp     bx,1234h             ; Compare BX with 1234h (4 bytes)
  15.  
  16. A more optimized way of doing this is:
  17.  
  18.          cmp     ax,1234h             ; Compare AX with 1234h (3 bytes)
  19.  
  20.   However this can ONLY be done when the AL/AX register DOESN'T hold an
  21. important value, but if the AL/AX register is used many times it COULD
  22. be more optimized to use it even if you have to PUSH it and then POP it
  23. afterwards.
  24.  
  25. ----------------------------------------------
  26. Use the Data Segment instead of other segments
  27. ----------------------------------------------
  28.   Moving a value from the memory to AX could be done like this:
  29.  
  30.          mov     ax,es:[si]           ; Move ES:[SI] to AX (3 bytes)
  31.  
  32. A more optimized way of doing this is:
  33.  
  34.          mov     ax,ds:[si]           ; Move DS:[SI] to AX (2 bytes)
  35.  
  36. ----------------
  37. Clear a register
  38. ----------------
  39.   Clearing a register could be done like this:
  40.  
  41.          mov     ax,00h              ; Clear AX (3 bytes)
  42.  
  43. A more optimized way of doing this is:
  44.  
  45.          sub     ax,ax               ; Clear AX (2 bytes)
  46.  
  47. Or a equally optimized way of this is:
  48.  
  49.          xor     ax,ax               ; Clear AX (2 bytes)
  50.  
  51. ---------------------
  52. Clear the DX register
  53. ---------------------
  54.   Clearing the DX register could be done like this:
  55.  
  56.          mov     dx,00h              ; Clear DX (3 bytes)
  57.  
  58. Or like this:
  59.  
  60.          xor     dx,dx               ; Clear DX (2 bytes)
  61.  
  62. A more optimized way of doing this is:
  63.  
  64.          cwd                         ; Convert word to doubleword (1 byte)
  65.  
  66. However this can ONLY be done if the AX register is less than 8000h.
  67.  
  68. ---------------------------
  69. Test if a register is clear
  70. ---------------------------
  71.   Testing if a register is clear could be done like this:
  72.  
  73.          cmp     ax,00h              ; AX = 0? (3 bytes)
  74.  
  75. A more optimized way of doing this is:
  76.  
  77.          or      ax,ax               ; AX = 0? (2 bytes)
  78.  
  79. ----------------------------------------------------
  80. Use a 16 bit register instead of two 8 bit registers
  81. ----------------------------------------------------
  82.   Moving a value to a 16 bit register could be done like this:
  83.  
  84.          mov     ah,12h              ; Move 12h to AH (2 bytes)
  85.          mov     al,34h              ; Move 34h to AL (2 bytes)
  86.  
  87. A more optimized way of doing this is:
  88.  
  89.          mov     ax,1234h             ; Move 1234h to AX (3 bytes)
  90.  
  91. However this can ONLY be done if the two 8 bit registers are the high and low
  92. register of the same 16 bit register.
  93.  
  94. ---------------------------------------------------------
  95. Move the AL/AX register to another register or vice versa
  96. ---------------------------------------------------------
  97.   Moving the AL/AX register to another register could be done like this:
  98.  
  99.          mov     bx,ax               ; Move AX to BX (2 bytes)
  100.  
  101. A more optimized way of doing this is:
  102.  
  103.          xchg    ax,bx               ; Exchange AX with BX (1 byte)
  104.  
  105.   However this can ONLY be done if the source registers value is unimportant
  106. afterwards, because the source register will hold the destination registers
  107. value.
  108.  
  109. -------------------------------
  110. Use DI/SI as base instead of BP
  111. -------------------------------
  112.   Moving a value from the memory to AX could be done like this:
  113.  
  114.          mov     ax,ds:[bp]           ; Move DS:[BP] to AX (3 bytes)
  115.  
  116. A more optimized way of doing this is:
  117.  
  118.          mov     ax,ds:[si]           ; Move DS:[SI] to AX (2 bytes)
  119.  
  120.   If the DI/SI index is used many times it COULD be more optimized to used
  121. the DI/SI index even if you have to PUSH it and then POP it afterwards.
  122.  
  123. --------------------------------------------------------
  124. Use the CMPS, LODS, MOVS, SCAS, STOS and REP instuctions
  125. --------------------------------------------------------
  126.   Moving a value from the memory to AX could be done like this:
  127.  
  128.          mov     ax,ds:[si]           ; Move DS:[SI] to AX (2 bytes)
  129.  
  130. A more optimized way of doing this is:
  131.  
  132.          lodsw                        ; Load AX with DS:[DI] (1 bytes)
  133.  
  134.   Remember to clear/set the direction flag. Sometimes it COULD be more
  135. optimized to use these instructions even if you have to PUSH and then POP the
  136. used registers/segments afterwards.
  137.  
  138. ---------------------------
  139. Move a segment to a segment
  140. ---------------------------
  141.   Moving a segment to a segment is weird, because you can't move a segment to
  142. another segment directly by:
  143.  
  144.          mov     ds,cs               ; Can't do this!
  145.  
  146. Because of that, you could use a register as a temporary storage, like this:
  147.  
  148.          mov     ax,cs               ; Move CS to AX (2 bytes)
  149.          mov     ds,ax               ; Move AX to DS (2 bytes)
  150.  
  151.   But if an important value is held by the AX register, you have to PUSH and
  152. the POP it afterwards, that would add the code by 2 bytes, a more optimized
  153. way of doing this is:
  154.  
  155.          push    cs                  ; Save CS at stack        (1 byte)
  156.          pop     ds                  ; Load DS from stack (CS) (1 byte)
  157.  
  158. -----------------------------------------------
  159. Use SHL/SHR instead of the DIV/MUL instructions
  160. -----------------------------------------------
  161.   Multiplying AL with 2 could be done like this:
  162.  
  163.          mov     bh,02h              ; Move 02h to BH (2 bytes)
  164.          mul     bh                  ; Multiply AL with BL (2 bytes)
  165.  
  166. A more optimized way of doing this is:
  167.  
  168.          shl     al,01h              ; Multiply AL with 02h (2 bytes)
  169.  
  170. This can ONLY be used if the source can be divided by 2.
  171.  
  172.  
  173. ----------------------------------------
  174. Use object codes instead of instructions
  175. ----------------------------------------
  176.   A far call could be done like this:
  177.  
  178.          call    far address         ; Make a far call (3 bytes)
  179. address      dd      ?                   ; Address of a procedure (4 bytes)
  180.  
  181. A more optimized way of doing this is:
  182.  
  183. callfar      db      9ah                 ; Object code of a far call (1 byte)
  184. address      dd      ?                   ; Address of a procedure (4 bytes)
  185.  
  186. This will ONLY optimize your code if the immediate value after the object 
  187. code is a word or greater.
  188.  
  189. --------------
  190. Use procedures
  191. --------------
  192.   If some code is used many times and it's size is large, it COULD be more
  193. optimized to use it as a procedure, the following formula can calculate if
  194. it is more optimized to use a procedure:
  195.  
  196. Bytes saved = (procedure size - 4) * number of invocations - procedure size
  197.  
  198.   Figure 4 in the parentheses of the formula is there because the size of the
  199. CALL and RET instructions together are 4 bytes.
  200.  
  201. ------------------------
  202. Make procedures flexible
  203. ------------------------
  204.   Make procedures flexible if possible, this CAN optimize your code, because
  205. the redundant code is removed, a example from this is:
  206.  
  207. movefptrend  proc    near                 ; Move file pointer to the end
  208.          mov     al,02h               ;  "        "      "   "   "
  209. movefileptr  proc    near                 ; Move file pointer to end/beginning
  210.          cwd                          ; Convert word to doubleword
  211. movefpointer proc    near                 ; Move file pointer to a offset
  212.          xor     dx,dx                ; Clear DX
  213.          mov     ah,42h               ; Move file pointer
  214.          int     21h                  ; Do it!
  215.          ret                          ; Return!
  216.          endp
  217.          endp
  218.          endp
  219.  
  220.   Use the formula from above to calculate if the flexible procedures can be
  221. used to optimize your code.
  222.  
  223. ----------------------------------
  224. Use all the information in the DTA
  225. ----------------------------------
  226.   DTA (Disk Transfer Area) is used by service 4eh and 4fh in the DOS functions
  227. interrupt (INT 21h), the contents of the DTA block are:
  228.  
  229.                 ----------------------------------------
  230.         Offset Size  Contents
  231.                 ----------------------------------------
  232.           00   Byte  Drive letter
  233.          01-0B Bytes Search template
  234.          0C-14 Bytes Reserved
  235.           15   Byte  File attribute
  236.          16-17 Word  File time
  237.          18-19 Word  File date
  238.          1A-1D DWord File size
  239.          1E-3A Bytes ASCIIZ filename + extension
  240.                 ----------------------------------------
  241.  
  242. - If your want to reset the files time and date afterwards, then use the
  243.   DTA instead of service 57h in INT 21h.
  244. - If you only want to infect one file, then change the drive letter to a
  245.   illegal value instead of making redundant code in the exit part of the
  246.   program, if you change the drive letter to a illegal value an error will
  247.   occur.
  248.  
  249. However, this will ONLY optimize your code, if you are already using the DTA.
  250.  
  251. ---------------------
  252. Final tips and tricks
  253. ---------------------
  254. - Remove all unnecessary NOPs
  255. - Move your code around, to see if some JUMP NEAR instructions could be
  256.   replaced by JUMP SHORT instructions etc.
  257. - Don't use instructions to calculate values that can be calculated 
  258.   directly in a parentheses.
  259. - Use LEA instead of MOV OFFSET.
  260. - Use the stack to store temporary data, but be careful if it is a COM file.
  261. - Use the CBW instructions to clear the AH register if AL is less than 80h.
  262. - Use DEC/INC instead of ADD/SUB register,01h.
  263. - When using DEC/INC it is more optimized to use 16 bits registers rather 
  264.   than 8 bit registers.
  265.  
  266.  
  267.  
  268.